package middleware

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/sirupsen/logrus"
	"net/http"
	"time"
)

const (
	CBlack = iota
	CRed
	CGreen
	CYellow
	CBlue
	CPurple
	CCyan
	CGray
	CWhite
)

func LogMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {

		// Start timer
		start := time.Now()
		path := c.Request.URL.Path
		raw := c.Request.URL.RawQuery

		// Process request
		c.Next()

		// Log only when path is not being skipped
		end := time.Now()
		latency := float64(end.Sub(start)) / 100000

		clientIP := c.ClientIP()
		method := c.Request.Method
		statusCode := c.Writer.Status()
		errorMessage := c.Errors.ByType(gin.ErrorTypePrivate).String()

		//bodySize := c.Writer.Size()

		if raw != "" {
			path = path + "?" + raw
		}
		// 设置颜色
		logrus.Infof("[GIN] %s |%s| %.2fms | %s |%s| %s \n %s",
			start.Format(time.DateTime),
			statusCodeColor(statusCode),
			latency,
			clientIP,
			methodColor(method),
			path,
			errorMessage,
		)
	}
}

func statusCodeColor(code int) string {
	switch {
	case code >= http.StatusOK && code < http.StatusMultipleChoices:
		return fmt.Sprintf("\033[4%dm%d\033[0m", CGreen, code)
	case code >= http.StatusMultipleChoices && code < http.StatusBadRequest:
		return fmt.Sprintf("\033[4%dm%d\033[0m", CWhite, code)
	case code >= http.StatusBadRequest && code < http.StatusInternalServerError:
		return fmt.Sprintf("\033[4%dm%d\033[0m", CYellow, code)
	default:
		return fmt.Sprintf("\033[4%dm%d\033[0m", CRed, code)
	}
}

func methodColor(method string) string {
	switch method {
	case http.MethodGet:
		return fmt.Sprintf("\033[4%dm%s\033[0m", CBlue, method)
	case http.MethodPost:
		return fmt.Sprintf("\033[4%dm%s\033[0m", CCyan, method)
	case http.MethodPut:
		return fmt.Sprintf("\033[4%dm%s\033[0m", CYellow, method)
	case http.MethodDelete:
		return fmt.Sprintf("\033[4%dm%s\033[0m", CRed, method)
	case http.MethodPatch:
		return fmt.Sprintf("\033[4%dm%s\033[0m", CGreen, method)
	case http.MethodHead:
		return fmt.Sprintf("\033[4%dm%s\033[0m", CPurple, method)
	case http.MethodOptions:
		return fmt.Sprintf("\033[4%dm%s\033[0m", CWhite, method)
	default:
		return fmt.Sprintf("\033[0m%s\033[0m", method)
	}
}
